package cn.edu.buaa.treehole.service;

import cn.edu.buaa.treehole.common.Pair;
import cn.edu.buaa.treehole.config.Settings;
import cn.edu.buaa.treehole.dao.ReplyDao;
import cn.edu.buaa.treehole.dao.SignatureDao;
import cn.edu.buaa.treehole.dao.exception.DaoException;
import cn.edu.buaa.treehole.dao.exception.PidNotExistException;
import cn.edu.buaa.treehole.dao.exception.RidNotExistException;
import cn.edu.buaa.treehole.dao.exception.SignatureNotExistException;
import cn.edu.buaa.treehole.pojo.ReplyInfo;
import cn.edu.buaa.treehole.pojo.dao.ReplyDaoInfo;
import cn.edu.buaa.treehole.pojo.dao.SignatureDaoInfo;
import cn.edu.buaa.treehole.pojo.fixedinfo.NamedReplyInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.net.http.HttpRequest;
import java.util.List;

@Service
public class ReplyInfoService {
    private final Logger logger = LoggerFactory.getLogger(ReplyInfoService.class);
    private final ReplyDao replyDao;
    private Settings settings;
    private NameService nameService;
    private ContentService contentService;
    private SignatureService signatureService;

    @Autowired
    public ReplyInfoService(ReplyDao replyDao) {
        this.replyDao = replyDao;
    }

    @Autowired
    public void setSettings(Settings settings) {
        this.settings = settings;
    }

    @Autowired
    public void setNameService(NameService nameService) {
        this.nameService = nameService;
    }

    @Autowired
    public void setContentService(ContentService contentService) {
        this.contentService = contentService;
    }

    @Autowired
    public void setSignatureService(SignatureService signatureService) {
        this.signatureService = signatureService;
    }

    @Override
    public String toString() {
        return "ReplyInfoService{" +
                ", replyDao=" + replyDao +
                '}';
    }

    public NamedReplyInfo getReplyInfo(long pid, long rid) throws RidNotExistException {
        if (rid <= 0) {
            throw new RidNotExistException("rid must greater than 0");
        }
        ReplyDaoInfo replyInfo = replyDao.selectReplyById(pid, rid);
        String name;
        if (replyInfo.getSignature().equals(settings.getAdminSignature())) {
            name = "ADMIN";
        }
        else {
            long nid = signatureService.ensureNidForReply(pid, replyInfo.getSignature());
            name = nameService.getName((int) nid);
        }
        return new NamedReplyInfo(
                replyInfo.getPid(),
                replyInfo.getRid(),
                contentService.getReplyContent(pid, rid),
                name,
                replyInfo.getTime()
        );
    }


    /*
    * @param info: rid不必初始化, 但其余属性都一定完成了初始化.
    * @return 返回分配给该回帖的昵称, 分配给改回帖的rid.
    * */
    @Transactional(rollbackFor = {DaoException.class, RuntimeException.class})
    public Pair<String, Long> addReply(ReplyInfo info) {
        synchronized (replyDao) {
            long rid = replyDao.selectMaxRidByPid(info.getPid());
            info.setRid(++rid);
            String name;
            int nid = signatureService.ensureNidForReply(info.getPid(), info.getSignature());
            name = nameService.getName(nid);

            contentService.addReplyContent(info.getPid(), info.getRid(), info.getContent());

            ReplyDaoInfo replyDaoInfo = new ReplyDaoInfo();
            replyDaoInfo.setTime(info.getDate());
            replyDaoInfo.setSignature(info.getSignature());
            replyDaoInfo.setPid(info.getPid());
            replyDaoInfo.setRid(info.getRid());
            replyDao.insertReply(replyDaoInfo);

            return Pair.valueOf(name, rid);
        }
    }

    @Transactional(rollbackFor = {DaoException.class, RuntimeException.class})
    public void deleteReply(long pid, long rid, String signature) throws SignatureNotExistException, RidNotExistException {
        ReplyDaoInfo info = replyDao.selectReplyById(pid, rid);
        if (rid <= 0) {
            throw new RidNotExistException("Cannot delete reply with id=0");
        }
        if (!info.getSignature().equals(signature)) {
            throw new SignatureNotExistException(toString()
                    + ".deleteReply(" + pid + ", " + rid + ", " + signature + ")");
        }
        replyDao.deleteReplyById(pid, rid);
        contentService.deleteReplyContent(pid, rid);
    }

    void deleteAllReplyByPid(long pid) {
        replyDao.deleteAllReplyByPid(pid);
    }
}
